/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.sensor;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import nl.cloudfarming.sensor.model.DataFileBO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Base Receiver implementation, uses the service loader to discover the
 * parsers and handler available and use those to process the payloads.
 *
 * @author Timon Veenstra
 */
public abstract class ServiceLoaderReceiver<P, R> implements Receiver<R> {

    private static Log log = LogFactory.getLog(ServiceLoaderReceiver.class);
    private ArrayList<ParsedUnit> unitList = new ArrayList<ParsedUnit>();

    public ParsedUnit dispatchParsing(P payload, DataFileBO dataFileBO){
        ServiceLoader<Parser> parserLoader = ServiceLoader.load(Parser.class);
        for (Parser parser : parserLoader) {
            if (parser.ableToParse(payload)) {
                try {
                    return(parser.parse(payload, dataFileBO));

                } catch (ParseException e) {
                    log.warn("Exception while receiving:"+e.getMessage());
                }
            }
        }
        return null;
    }

    public void dispatchHandling(P payload, DataFileBO dataFileBO) throws NoSuchAlgorithmException, IOException {
        ServiceLoader<Parser> parserLoader = ServiceLoader.load(Parser.class);

        loaders:
        for (Parser parser : parserLoader) {
            if (parser.ableToParse(payload)) {
                try {
                    unitList.add(parser.parse(payload, dataFileBO));
                    if (unitList.size() % 250 == 0) {
                        sendToHandlers(unitList);
                        unitList.clear();
                    }
                } catch (ParseException e) {
                    log.warn("Exception while receiving:"+e.getMessage());
                }
            }
        }
    }

    public void sendRemainderToHandlers(){
        sendToHandlers(unitList);
        unitList.clear();
    }


    public void sendToHandlers(List<ParsedUnit> parsedUnitList) {
        ServiceLoader<Handler> handlerLoader = ServiceLoader.load(Handler.class);
        for (Handler handler : handlerLoader) {
            if (handler.canHandle(parsedUnitList)) {
                handler.handle(parsedUnitList);
            }
        }
    }
}
